﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using diploma.core.data.objects;
using System.Reflection;

namespace diploma.core.data
{
    public enum DataObjectTypes : int
    {
        Method = 1,
        ObjectType = 2,
        Problem = 3,
        Property = 4,
        Question = 5,
        Statement = 6,
        Term = 7,
        Theme = 8,
        Theorem = 9,
        Unknow = 100
    }
    /// <summary>
    /// Базовый класс для источника данных
    /// </summary>
    public abstract class DataSource
    {
        private Dictionary<DataObjectTypes, string> all = new Dictionary<DataObjectTypes, string>();
        protected System.Reflection.Assembly assembly;
        /// <summary>
        /// Settings:
        ///     FireBird: 
        ///         0 - server-host,
        ///         1 - user,
        ///         2 - password,
        ///         3 - database name;
        ///     MySql: 
        ///         0 - server-host,
        ///         1 - port,
        ///         2 - user,
        ///         3 - password,
        ///         4 - database name;
        /// </summary>
        protected List<string> settings;

        /// <summary>
        /// Подключение
        /// </summary>
        protected bool connection = false;

        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="_settings">Настроки для источника данных</param>
        public DataSource(IEnumerable<string> _settings)
        {
            all.Add(DataObjectTypes.Method, "Methods");
            all.Add(DataObjectTypes.ObjectType, "ObjectTypes");
            all.Add(DataObjectTypes.Problem, "Problems");
            all.Add(DataObjectTypes.Property, "Properties");
            all.Add(DataObjectTypes.Question, "Questions");
            all.Add(DataObjectTypes.Statement, "Statements");
            all.Add(DataObjectTypes.Term, "Terms");
            all.Add(DataObjectTypes.Theme, "Themes");
            all.Add(DataObjectTypes.Theorem, "Theorems");
            settings = new List<String>(_settings);
            connect();

        }

        /// <summary>
        /// Попытка подключения
        /// </summary>
        abstract protected void connect();

        /// <summary>
        /// Показывает, есть ли связь с базой
        /// </summary>
        public bool isConnect
        {
            get
            {
                return connection;
            }
        }

        #region Resources Functions
        protected Stream getEmbeddedFile(System.Reflection.Assembly a, string fileName)
        {
            try
            {

                string name = a.GetName().Name;
                string[] ass = a.GetManifestResourceNames();
                Stream str = a.GetManifestResourceStream(name + "." + fileName);
                if (str == null)
                    throw new Exception("Could not locate embedded resource '" + fileName + "' in assembly '" + name + "'");
                return str;
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        protected String getFileContent(Stream s)
        {
            StreamReader reader = new StreamReader(s);
            string res = reader.ReadToEnd();
            reader.Close();
            s.Close();
            return res;
        }
        #endregion;

        public virtual void MakeAction(DataObjectTypes dataObjectTypes, DataActions _action, params object[] parameters)
        {
            string manifestModule = assembly.ManifestModule.Name;
            Type ds = typeof(object);
            foreach (Type dsType in assembly.GetModule(manifestModule).GetTypes())
            {
                if (dsType.BaseType.Name.ToLower() == "datasource")
                {
                    ds = dsType;
                    break;
                }
            }
            string methodName = (_action == DataActions.getAll ? _action.ToString() + all[dataObjectTypes] : _action.ToString() + dataObjectTypes.ToString());
            System.Reflection.MethodInfo method = ds.GetMethod(methodName);
            if (method.ReturnType.IsGenericType)
            {
                DataRouter.LastReturn = method.Invoke(this, new object[] { });
            }
            else
            {
                if (method.ReturnType.IsClass)
                {
                    DataRouter.LastReturn = method.Invoke(this, parameters);
                }
                else
                {
                    method.Invoke(this, parameters);
                }
            }
        }

        #region Properties

        public abstract void deleteProperty(long _id);
        public abstract Property insertProperty(Property _property);
        public abstract Property updateProperty(Property _property);
        public abstract List<Property> getAllProperties();
        public abstract Property getProperty(long _id);

        #endregion


        #region Methods
        public abstract void deleteMethod(long _id);
        public abstract Method insertMethod(Method _method);
        public abstract Method updateMethod(Method _method);
        public abstract List<Method> getAllMethods();
        public abstract Method getMethod(long _id);
        #endregion


        #region ObjectTypes
        public abstract void deleteObjectType(long _id);
        public abstract ObjectType insertObjectType(ObjectType _objecttype);
        public abstract ObjectType updateObjectType(ObjectType _objecttype);
        public abstract List<ObjectType> getAllObjectTypes();
        public abstract ObjectType getObjectType(long _id);
        #endregion

        #region Problems
        public abstract void deleteProblem(long _id);
        public abstract Problem insertProblem(Problem _problem);
        public abstract Problem updateProblem(Problem _problem);
        public abstract List<Problem> getAllProblems();
        public abstract Problem getProblem(long _id);
        #endregion

        #region Statements
        public abstract void deleteStatement(long _id);
        public abstract Statement insertStatement(Statement _statement);
        public abstract Statement updateStatement(Statement _statement);
        public abstract List<Statement> getAllStatements();
        public abstract Statement getStatement(long _id);
        #endregion

        #region Themes
        public abstract void deleteTheme(long _id);
        public abstract Theme insertTheme(Theme _theme);
        public abstract Theme updateTheme(Theme _theme);
        public abstract List<Theme> getAllThemes();
        public abstract Theme getTheme(long _id);
        #endregion

        #region Theorems
        public abstract void deleteTheorem(long _id);
        public abstract Theorem insertTheorem(Theorem _theorem);
        public abstract Theorem updateTheorem(Theorem _theorem);
        public abstract List<Theorem> getAllTheorems();
        public abstract Theorem getTheorem(long _id);
        #endregion

        #region Questions

        public abstract List<Question> getAllQuestions();
        public abstract Question insertQuestion(Question _question);
        public abstract Question updateQuestion(Question _question);
        public abstract Question getQuestion(long _id);
        public abstract void deleteQuestion(long _id);

        #endregion

        #region Terms

        public abstract List<Term> getAllTerms();
        public abstract Term insertTerm(Term _term);
        public abstract Term updateTerm(Term _term);
        public abstract Term getTerm(long _id);
        public abstract void deleteTerm(long _id);

        #endregion

    }
}
